package com.zzs.client.service.impl;

import cn.hutool.core.util.RandomUtil;
import com.zzs.client.dao.mysql.UserMapper;
import com.zzs.client.entity.mysql.UserDO;
import com.zzs.client.pojo.bo.user.UpdateInfoBO;
import com.zzs.client.pojo.vo.user.UserDetailVO;
import com.zzs.client.service.UserInfoService;
import com.zzs.common.core.constant.RedisKeyConsts;
import com.zzs.common.core.enums.ResponseCode;
import com.zzs.common.core.util.ThreadLocalUtil;
import com.zzs.common.minio.entity.File;
import com.zzs.common.minio.service.MinioService;
import com.zzs.common.redis.service.RedisService;
import com.zzs.common.security.exception.ServiceException;
import com.zzs.common.security.util.PasswordUtil;
import com.zzs.common.sms.service.SmsService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.util.regex.Pattern;

/**
 * @author zzs
 * @date 2025/03/26
 */
@Service
public class UserInfoServiceImpl implements UserInfoService {
    @Autowired
    private UserMapper userMapper;

    @Autowired
    private MinioService minioService;

    @Autowired
    private SmsService smsService;

    @Autowired
    private RedisService redisService;

    @Override
    public UserDetailVO getUserDetail(long userId) {
        UserDO userDO = userMapper.getUserDetail(userId);
        if (userDO == null) {
            throw new ServiceException(ResponseCode.USER_NO_EXISTS);
        }
        UserDetailVO userDetailVO = new UserDetailVO();
        BeanUtils.copyProperties(userDO, userDetailVO);
        userDetailVO.setPhone(maskPhoneNumber(userDetailVO.getPhone()));
        return userDetailVO;
    }

    private String maskPhoneNumber(String phoneNumber) {
        // 获取前3位和后4位
        String prefix = phoneNumber.substring(0, 3);
        String suffix = phoneNumber.substring(phoneNumber.length() - 4);
        // 中间部分用*替换
        String masked = phoneNumber.substring(3, phoneNumber.length() - 4).replaceAll(".", "*");
        return prefix + masked + suffix;
    }

    @Override
    public File updateUserAvatar(MultipartFile file) {
        try {
            File file1 =  minioService.uploadImage(file);
            Long userId = ThreadLocalUtil.getUserId();
            if (userId == null) {
                throw new ServiceException(ResponseCode.UNAUTHORIZED);
            }
            userMapper.uploadAvatar(userId, file1.getUrl());
            return file1;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void updateUserInfo(UpdateInfoBO updateInfoBO) {
        UserDO userDO = new UserDO();
        BeanUtils.copyProperties(updateInfoBO, userDO);
        int effectRows = userMapper.updateInfo(userDO);
        if (effectRows != 1) {
            throw new ServiceException(ResponseCode.FAIL, "修改用户信息失败");
        }
    }

    @Override
    public void sendCodeToOldPhone(String phone) {
        if (!isValidChinesePhone(phone)) {
            throw new ServiceException(ResponseCode.FAIL, "手机号格式错误");
        }
        Long userId = ThreadLocalUtil.getUserId();
        if (userId == null) {
            throw new ServiceException(ResponseCode.UNAUTHORIZED);
        }
        if (!phone.equals(userMapper.getPhone(userId))) {
            throw new ServiceException(ResponseCode.FAIL, "手机号不匹配");
        }
        String key = RedisKeyConsts.getOldPhoneCodeKey(phone);
        if (redisService.hasKey(key)) {
            throw new ServiceException(ResponseCode.FAIL, "验证码已发送，请稍后再试");
        }
//        生成6位随机验证码
        String randomNum = RandomUtil.randomNumbers(6);
        smsService.sendSmsCode(phone, randomNum);
        redisService.saveValue(key, randomNum, RedisKeyConsts.getOldPhoneCodeExpireTime(), RedisKeyConsts.getOldPhoneCodeTimeUnit());
    }

    @Override
    public void verifyOldPhone(String phone, String code) {
        String oldPhoneCodeKey = RedisKeyConsts.getOldPhoneCodeKey(phone);
        checkCode(oldPhoneCodeKey, code);
        Long userId = ThreadLocalUtil.getUserId();
        if (userId == null) {
            throw new ServiceException(ResponseCode.UNAUTHORIZED);
        }
        redisService.saveValue(RedisKeyConsts.getChangePhoneKey(userId), 1, RedisKeyConsts.getChangePhoneExpireTime(), RedisKeyConsts.getChangePhoneTimeUnit());
        redisService.removeKey(RedisKeyConsts.getOldPhoneCodeKey(phone));
    }

    @Override
    public void sendCodeToNewPhone(String phone) {
        if (!isValidChinesePhone(phone)) {
            throw new ServiceException(ResponseCode.FAIL, "手机号格式错误");
        }
        Long userId = ThreadLocalUtil.getUserId();
        if (userId == null) {
            throw new ServiceException(ResponseCode.UNAUTHORIZED);
        }
        if (!redisService.hasKey(RedisKeyConsts.getChangePhoneKey(userId))) {
            throw new ServiceException(ResponseCode.FAIL, "请先验证旧手机号");
        }
        String key = RedisKeyConsts.getNewPhoneCodeKey(phone);
        if (redisService.hasKey(key)) {
            throw new ServiceException(ResponseCode.FAIL, "验证码已发送，请稍后再试");
        }
//        生成6位随机验证码
        String randomNum = RandomUtil.randomNumbers(6);
        smsService.sendSmsCode(phone, randomNum);
        redisService.saveValue(key, randomNum, RedisKeyConsts.getNewPhoneCodeExpireTime(), RedisKeyConsts.getNewPhoneCodeTimeUnit());
    }

    @Override
    public void verifyNewPhone(String phone, String code) {
        if (!isValidChinesePhone(phone)) {
            throw new ServiceException(ResponseCode.FAIL, "手机号格式错误");
        }
        String key = RedisKeyConsts.getNewPhoneCodeKey(phone);
        checkCode(key, code);


        Long userId = ThreadLocalUtil.getUserId();
        if (userId == null) {
            throw new ServiceException(ResponseCode.UNAUTHORIZED);
        }
        redisService.removeKey(RedisKeyConsts.getChangePhoneKey(ThreadLocalUtil.getUserId()));
        redisService.removeKey(key);
        userMapper.updatePhone(userId, phone);
    }

    @Override
    public void sendCodeToUpdatePassword(String phone) {
        if (!isValidChinesePhone(phone)) {
            throw new ServiceException(ResponseCode.FAIL, "手机号格式错误");
        }
        String key = RedisKeyConsts.getUpdatePasswordCodeKey(phone);
        if (redisService.hasKey(key)) {
            throw new ServiceException(ResponseCode.FAIL, "验证码已发送，请稍后再试");
        }
//        生成6位随机验证码
        String randomNum = RandomUtil.randomNumbers(6);
        smsService.sendSmsCode(phone, randomNum);
        redisService.saveValue(key, randomNum, RedisKeyConsts.getUpdatePasswordCodeExpireTime(), RedisKeyConsts.getUpdatePasswordCodeTimeUnit());
    }

    @Override
    public void updatePassword(String phone, String code, String password, String passwordRepeat) {
        if (!password.equals(passwordRepeat)) {
            throw new ServiceException(ResponseCode.FAIL, "两次密码不一致");
        }
        String key = RedisKeyConsts.getUpdatePasswordCodeKey(phone);
        checkCode(key, code);
        Long userId = ThreadLocalUtil.getUserId();
        if (userId == null) {
            throw new ServiceException(ResponseCode.UNAUTHORIZED);
        }
        String encryptPassword = PasswordUtil.encryptPassword(password);
        userMapper.updatePassword(userId, encryptPassword);
    }

    private void checkCode(String redisKey, String code) {
        String codeInRedis = redisService.getValue(redisKey, String.class);
        if (codeInRedis == null || codeInRedis.isBlank()) {
            throw new ServiceException(ResponseCode.FAIL, "请先获取验证码");
        }
        if (!codeInRedis.equals(code)) {
            throw new ServiceException(ResponseCode.FAIL, "验证码错误");
        }
    }


    private boolean isValidChinesePhone(String phone) {
        if (phone == null || phone.trim().isEmpty()) {
            return false;
        }
        String regex = "^1[3-9]\\d{9}$";
        Pattern pattern = Pattern.compile(regex);
        return pattern.matcher(phone).matches();
    }
}
